package com.homework.papertexting.filter;

import com.homework.papertexting.util.JwtUtil; // 引入你的 JwtUtil
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; // 引入 UserDetailsService
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component; // 引入 Component 让 Spring 管理

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter; // 引入 OncePerRequestFilter

import java.io.IOException;

import org.slf4j.Logger; // 添加这一行
import org.slf4j.LoggerFactory; // 添加这一行

@Component // 标记为 Spring 组件，让 Spring 能够自动扫描和管理
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    // 添加 Logger 声明
    private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);

    @Autowired
    private JwtUtil jwtUtil; // 注入 JwtUtil

    @Autowired
    private UserDetailsService userDetailsService; // 注入 UserDetailsService，用于加载用户详情

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        // 获取请求路径和方法
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        logger.info("Processing request: {} {}", method, requestURI); // 添加日志

        // 1. 从请求头中获取 JWT (通常在 Authorization 头部)
        final String authorizationHeader = request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        // 记录 Authorization Header 状态
        logger.info("Authorization Header: {}", authorizationHeader != null ? "Present" : "Absent"); // 添加日志

        // 检查 Authorization 头部是否存在且以 "Bearer " 开头
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7); // 提取 token 字符串 (去掉 "Bearer ")
            try {
                username = jwtUtil.extractUsername(jwt); // 从 token 中提取用户名
                logger.info("Extracted username: {}", username); // 添加日志
            } catch (Exception e) {
                // 处理 token 解析或验证异常，例如 token 过期、签名错误等
                // 实际应用中应该记录日志或返回特定的错误响应
                logger.error("JWT validation error: " + e.getMessage());
                // 可以在这里记录更详细的异常信息
            }
        }

        // 记录 Security Context 状态 BEFORE filter processing
        Authentication authenticationBefore = SecurityContextHolder.getContext().getAuthentication();
        logger.info("Authentication BEFORE filter: {}", authenticationBefore != null ? authenticationBefore.getClass().getName() : "None"); // 添加日志


        // 2. 如果成功提取到用户名 并且 当前没有用户在 Spring Security 上下文中认证过
        // 注意：如果用户已经通过其他方式（例如 Session）认证过，这里就不会再次认证
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            // 3. 使用 UserDetailsService 加载用户详情
            // 需要确保你的 UserDetailsService 实现能够根据用户名加载用户
            // 这通常意味着你需要一个实现了 UserDetailsService 接口的类
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
            logger.info("Loaded UserDetails for username: {}", userDetails != null ? userDetails.getUsername() : "None"); // 添加日志

            // 4. 校验 token 是否有效 (比如未过期，签名正确等)
            if (jwtUtil.isTokenValid(jwt, userDetails)) {
                logger.info("JWT is valid for user: {}", username); // 添加日志

                // 5. 创建认证对象并设置到 Spring Security 上下文
                // UsernamePasswordAuthenticationToken 是一个常用的认证对象
                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities()); // credentials 通常设为 null，因为 JWT 本身就是凭证

                authenticationToken.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails(request)); // 设置请求详情

                // 将认证对象设置到 SecurityContextHolder，表示当前用户已认证
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                logger.info("Authentication set in SecurityContextHolder for user: {}", username); // 添加日志
            } else {
                logger.warn("JWT is not valid for user: {}", username); // 添加日志
            }
        } else {
            if (username == null) {
                // logger.info("No username extracted from JWT"); // 避免日志过多，根据需要开启
            }
            if (SecurityContextHolder.getContext().getAuthentication() != null) {
                logger.info("User already authenticated in SecurityContextHolder: {}", SecurityContextHolder.getContext().getAuthentication().getName()); // 添加日志
            }
        }

        // 继续过滤链处理前记录状态
        Authentication authenticationAfter = SecurityContextHolder.getContext().getAuthentication();
        logger.info("Authentication AFTER filter: {}", authenticationAfter != null ? authenticationAfter.getClass().getName() : "None"); // 添加日志


        // 6. 继续过滤链的处理
        // 这行是必须的，它将请求传递给下一个过滤器或最终的目标资源
        filterChain.doFilter(request, response);
    }
}